<?php
/**
 * Model class for ORM
 * @author Joe Minichino <joe@dsforge.net>
 * 
 */

class Model {
    /**
     * @example $table = "users";
     * @var string  table name for the model
     */
    protected $table;
    /**
     * @example $fields = array("id","username","password");
     * @var array array of fields that are mapped to the object.
     */
    protected $fields;
    
    /**
     * @example $defaults = array("status" => "OPEN","assigned_to" => "1");
     * @var array array of default values 
     */
    protected $defaults = array();
    
    /**
     * @example $mappings = array( "user_id" => "User" );
     * @var array array of properties and classes that map to properties, references id of another table
     */
    protected $mappings = array();
    
    /**
     * @example $sort = array("id","desc");
     * @var array  array of properties to sort the results
     */
    protected $sort = array();
    
    
    function  __construct() {

    }

    public static function get($class, $id){
        return DB::get()->getObject($class,$id);
    }
    
    /**
     * This method makes sure that the debug function is called in case the constant DEBUG is set to true
     * @param string $name name of property
     * @param string $value value of property
     */
    public function  __set($name, $val) {
        
        if(in_array($name, array_values($this->mappings) ) ){
            
            Debug::log("Passed obj : " . $val->toString());
            
            foreach($this->mappings as $key=>$value){
                Debug::log("Looking for $name : $value");
                if($value==$name){
                    //$obj = @DB::get()->getObject($name,$this->$key);
                    $this->$key = $val->id;
                    Debug::log( "Key: $key set to ".$this->$key  );
                    return;
                }
            }
        }
        $this->$name = $val;
        Debug::log( "$name set to ".$this->$name  );
        
    }

    public function __get($name){
        Debug::log("calling get for " . __CLASS__);
        
        if(in_array($name, array_values($this->mappings) ) ){
            foreach($this->mappings as $key=>$value){
                Debug::log("Looking for $name : $value");
                if($value==$name){
                    return @DB::get()->getObject($name,$this->$key);
                }
            }
        }
        return $this->$name;
    }

    // queries functions, you don't need to ever re-write them or override them
    public function getInsertQuery(){
        
        foreach($this->defaults as $key=>$value) $this->$key = $value;
        
        $values = "";
        foreach($this->fields as $field){
            $var = ($this->$field == "" || $this->$field==null )? "NULL" : "'" . mysqli_escape_string( DB::get()->getDb() , $this->$field) . "'";
            if($field!="id") { $values .= "," . $var; } else { $values .= ",NULL";}
        }
        $query = "insert into " . $this->table . "(" . wrapFields($this->fields) . ") values (" . substr($values,1) . ")";
        Debug::log("Class: " . get_class($this) .", query: " . $query);
        return $query;
    }

    public function getUpdateQuery(){
        $values = "";
        foreach($this->fields as $field){
            $values .= ", $field='" . mysqli_escape_string( DB::get()->getDb(), $this->$field) . "'";
        }
        $values = substr($values,1);
        $query = "update " . $this->table . " set $values where id=" . $this->id;
        Debug::log("Class: " . get_class($this) .", query: " . $query);
        return $query;
    }

    public function getDeleteQuery(){
        $query = "delete from " . $this->table . " where id = " . $this->id;
        Debug::log("Class: " . get_class($this) .", query: " . $query); 
        return $query;
    }

    public function getQuery($value, $param="id", $op="=",$offset=0, $limit=null){
        $limit_query = isset($limit) ? " limit $offset, $limit" : "";
        $orderby = "";
        foreach($this->sort as $field=>$order){
            $orderby .= ", $field $order";
        }
        $orderby = substr($orderby,1);
        $orderClause = count($this->sort) > 0 ?  " order by $orderby " : "";
        
        $query = "select * from " . $this->table . " where $param $op '$value' $orderClause" . $limit_query ;
        
        Debug::log("Class: " . get_class($this) .", query: " . $query); 
        return $query;
    }

    public function getWhereQuery($whereClause,$offset=0,$limit=null){
        $limit_query = isset($limit) ? " limit $offset, $limit" : "";
        $query = "select * from " . $this->table . " where $whereClause " . $limit_query ;
        Debug::log("Class: " . get_class($this) .", query: " . $query); 
        return $query;
    }

    /**
     * string representation of object
     * @return string string representation of object values 
     */
    public function toString(){
        $array = array();
        foreach($this->fields as $field): $array[] = "$field : {$this->$field}";        endforeach;
        return implode(", ", $array);
    }
    
    public function FGFormat(){
        $id = $this->id;
        $cell = array();
        foreach($this->fields as $field){

            $cell[$field] = $this->$field;
        }
        
        $entry = array(
            'id'=>$id,
            'cell' => $cell
        );
        
        return $entry;
    }

}